卷積中的stride和padding
卷積神經網路(Convolutional neural network, CNN):卷積計算中的步伐(stride)和填充(padding)
卷積神經網路(Convolutional neural network, CNN)其他相關連結我也一起列上來*
*NN-2–1 卷積神經網路(Convolutional neural network, CNN) — 卷積運算、池化運算
NN-2–2 卷積神經網路(Convolutional neural network, CNN) — CNN運算流程
NN-2–3 卷積神經網路(Convolutional neural network, CNN):卷積計算的倒傳遞推導與稀疏矩陣觀點來看卷積計算
NN-2–4 卷積神經網路(Convolutional neural network, CNN):卷積計算中的步伐(stride)和填充(padding)
NN-2–5 卷積神經網路(Convolutional neural network, CNN): 1×1卷積計算在做什麼
一般看到的卷積介紹,大概就像上圖,圖會因為你的kernel map大小做完卷積後變的更小,實際上卷積怎麼執行可以參考我之前寫的:
卷積神經網路(Convolutional neural network, CNN) — 卷積運算、池化運算
Note: (2019/01/15增加)一般卷積網路過程中,除了Input image不稱為Feature map外,中間產生的圖我們都稱之為Feature map,原因很簡單就是這些中間產生的圖都是為了「描繪出該任務所應該產生對應的特徵資料」,這也呼應Yann LeCun, Yoshua Bengio & Geoffrey Hinton寫的Deep Learning第一句話寫的「Deep learning allows computational models that are composed of multiple processing layers to learn representations of data with multiple levels of abstraction」,深度學習過程就是在學資料的特性,所以中間出來的結果都是特徵資料,在影像因為是2D,所以用Feature map來稱呼。
所以一個卷積計算基本上有幾個部份:
\1. 輸入的圖: 假設大小是W × W。
\2. Filter (kernel map)大小是 ks × ks
\3. Stride: kernel map在移動時的步伐長度 S
\4. 輸出的圖大小為 new_height × new_width
上圖的例子
\1. 輸入的圖: W × W =10 × 10。
\2. Filter (kernel map): ks × ks=3 × 3
\3. Stride: S=1
\4. 輸出的圖大小為 new_height × new_width = 8 × 8
上圖的範例產生了2個問題
\1. 是不是卷積計算後,卷積後的圖是不是就一定只能變小?
\2. 卷積計算是不是一次只能移動一格?
所以如果你有玩過deep learning的API,卷積計算部份除了基本的input和filter (kernel map)通常還有兩個參數可以調(strides, padding),這邊舉tensorflow的例子:
tf.nn.conv2d(input, filter, strides\, padding\, use_cudnn_on_gpu=None, data_format=None, name=None)
strides\和 padding\這兩個參數就是在解決上面說的兩個問題。
是不是卷積計算後,卷積後的圖是不是就一定只能變小?
ANS: 用zero padding
這個手法就是看你會消失多少的大小,在輸入的圖部份就給你加上0元素進去,這個手法稱為zero padding,實際作法如下圖。
此刻的卷積計算如下,這樣卷積後的圖就不會變小了。
上圖舉的例子是kernel map是3x3,假設kernel map為5x5,此刻在輸入的圖上下左右行和列都各加2行和2列的0,讓圖變成14x14,就可以了。
卷積計算是不是一次只能移動一格?
ANS: 當然不是,也可以2格3格,但此時卷積後的圖就會變的更小。
在tensorflow,padding那邊給了兩個選項「padding = ‘VALID’」和「padding = ‘SAME’」
padding = ‘VALID’ 等於最一開始敘述的卷積計算,圖根據filter大小和stride大小而變小。
公式如下: new_height = new_width = (W — F + 1) / S (结果向上取整數,假設算出來結果是4.5,取5)
剛剛的例子
filter 3x3, stride=1, 卷積後的大小: (10–3+1)/1=8
filter 3x3, stride=2, 卷積後的大小: (10–3+1)/2=4
padding = ‘SAME’,會用zero-padding的手法,讓輸入的圖不會受到kernel map的大小影響。
new_height = new_width = W / S (结果向上取整數)
剛剛的例子,filter 3x3, stride=2, 卷積後的大小: 10/2=5 (這邊我沒有做這張圖,可以自己想像一下,做法如下所述)
這邊的作法會先補zero-padding的0元素,然後在作stride=2的卷積,所以實際上是最(10+2)*(10+2)的圖做padding = ‘VALID’的事情,(12–3+1)/2=5。
Padding補充說明 (2019/01/15增加此內容)
上面介紹的公式是針對tensorflow內建的function功能(「padding = ‘VALID’」和「padding = ‘SAME’」),並不是一般算卷積後算新的feature map長寬的公式。
一般卷積後算新的feature map長寬的公式如下:
floor(1.1)=1, floor(1.6)=1
這邊跟前面差別在這邊多了一個pad參數。
對應到caffe prototxt卷積的參數會這麼寫,如下(其他模組應該是一樣可以設pad參數)
1 | convolution_param { |
這代表卷積層filter數設定為32,filter的kernel size是3,步伐stride是2,pad是1。pad=1,表示圖外圈額外加1圈0,假設pad=2,圖外圈額外加2圈0,以此類推。
所以kernel size是3的時候,你希望卷積後圖的寬高不要變,pad就要設定為1
假設kernel size是5的時候,你希望卷積後圖的寬高不要變,pad就要設定為2
假設kernel size是7的時候,你希望卷積後圖的寬高不要變,pad就要設定為3
Note: 因為一般大多只會用到卷積後,Feature map寬高會依據kernel size縮小一點(「padding = ‘VALID’」)或Feature map寬高不變(「padding = ‘SAME’」),鮮少搞一些特殊的功能,比如1×1卷積還要加pad=1,這樣出來的圖會比原本大一圈,而且這一圈還全為0。
而且一般卷積網路都是希望卷積後圖越來越小(整體MACC計算量才會小),除了segmentation和一些multi-scale object detection等才會用到deconv.或是一些upsample的方法把feature map放大。
Tensorflow是提供簡單的api,你就不需要自己去算pad要設多少,直接下strin即可(如下說明),多方便阿。**padding**
: A string
from: "SAME", "VALID"
. The type of padding algorithm to use.